#include "parkEvent.hpp"

#include "atomic.hpp"
#include "stdlib.h"

ParkEvent *volatile ParkEvent::FreeList = NULL;

ParkEvent *ParkEvent::Allocate(Thread *t)
{
    ParkEvent *ev;
    // 1、将FreeList下的列表变为私有列表
    for (;;)
    {
        ev = FreeList;
        if (ev == NULL)
        {
            break;
        }
        if (Atomic::cmpxchg_ptr(NULL, &FreeList, ev) != ev)
        {
            continue;
        }
        // 2、私有列表中获取一个ParkEvent使用
        ParkEvent *list = ev->FreeList;
        if (list == NULL)
        {
            break;
        }
        // 3、把私有列表与FreeList中新释放的ParkeEvent列表合并，然后赋值给FreeList
        for (;;)
        {
            ParkEvent *Arv = (ParkEvent *)Atomic::cmpxchg_ptr(list, &FreeList, NULL);
            if (Arv == NULL)
            {
                break;
            }

            if (Atomic::cmpxchg_ptr(NULL, &FreeList, Arv) != Arv)
            {
                continue;
            }

            ParkEvent *Tail = list;
            while (Tail->FreeNext != NULL)
                Tail = Tail->FreeNext;

            Tail->FreeNext = Arv;
        }
        break;
    }

    if (ev == NULL)
    {
        ev = new ParkEvent();
    }

    ev->FreeList = NULL;
    return ev;
}

void ParkEvent::Release(ParkEvent *e)
{
    if (e == NULL)
        return;

    for (;;)
    {
        ParkEvent *list = FreeList;
        e->FreeNext = list;
        if (Atomic::cmpxchg_ptr(e, &FreeList, list) == list)
        {
            break;
        }
    }
}

void *ParkEvent::operator new(size_t sz) throw()
{
    return (void*)
            ((intptr_t(::malloc(sz + 256)) + 256) & -256);

}
void ParkEvent::operator delete(void *a)
{
    ShouldNotReachHere();
}